import streamlit as st
import streamlit_antd_components as sac
from typing import Dict, Any, Callable, List

class MenuManager:
    _instance = None

    @classmethod
    def get_instance(cls, reset: bool = False):
        """获取MenuManager单例
        Args:
            reset: 是否重置实例
        """
        if reset:
            cls._instance = None
        if cls._instance is None:
            cls._instance = MenuManager()
        return cls._instance

    def __init__(self):
        if MenuManager._instance is not None:
            raise Exception("MenuManager是单例类，请使用get_instance()获取实例")
        MenuManager._instance = self
        self._menus = {}
        self._handlers = {}
        self._child_menu_keys = {}  # 存储子菜单label到key的映射

    def register(self, key: str, handler: Callable, parent: str = None, **menu_args):
        """注册菜单项
        Args:
            key: 菜单项标识
            handler: 处理函数
            parent: 父菜单的key
            **menu_args: MenuItem的参数
        """
        if parent:
            parent_menu = self._menus.get(parent)
            if parent_menu:
                children = parent_menu.get("children", [])
                # 保存子菜单的label和key的映射
                self._child_menu_keys[menu_args["label"]] = key
                children.append(sac.MenuItem(**menu_args))
                parent_menu["children"] = children
        else:
            self._menus[key] = menu_args
        self._handlers[key] = handler

    def _find_handler_by_label(self, label: str) -> Callable:
        """查找菜单项的处理函数"""
        # 先检查子菜单
        if label in self._child_menu_keys:
            return self._handlers[self._child_menu_keys[label]]
        # 再检查顶级菜单
        for key, menu in self._menus.items():
            if menu.get("label") == label:
                return self._handlers[key]
        return None

    def show_menu(self, index: int = 0):
        """显示所有已注册的菜单项并处理页面跳转
        Args:
            index: 默认选中的菜单索引
        """
        menu_items = [
            sac.MenuItem(**menu_args)
            for menu_args in self._menus.values()
        ]

        with st.sidebar:
            st.divider()
            with st.container(key="sidebar-sacmenu"):
                selected_page = sac.menu(
                    menu_items,
                    indent=6,
                    open_all=True,
                    index=index,
                )

        if selected_page:
            handler = self._find_handler_by_label(selected_page)
            if handler:
                handler()
